﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.HomeServer.Controls;
using Serviio.API;

namespace Serviio.WHS
{
    public partial class LibraryTabControl : UserControl
    {
        private static readonly LogFacade log = LogFacade.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public LibraryTabControl()
        {
            InitializeComponent();
        }
        
        private ServiioConnection conn = null;

        public void Initialize(ServiioConnection connection)
        {
            try
            {
                if (this.conn != null)
                    return;

                log.Info("Initializing...");

                this.conn = connection;

                timerLibraryStatus.Enabled = true;

                comboBoxMaxNumberOfItemsForOnlineFeeds.DataSource = new BindingSource(connection.Reference.OnlineMaxItemsChoices, null);
                comboBoxMaxNumberOfItemsForOnlineFeeds.DisplayMember = "Value";
                comboBoxMaxNumberOfItemsForOnlineFeeds.ValueMember = "Key";

                comboBoxOnlineContentPreferredQuality.DataSource = new BindingSource(connection.Reference.OnlineContentQualities, null);
                comboBoxOnlineContentPreferredQuality.DisplayMember = "Value";
                comboBoxOnlineContentPreferredQuality.ValueMember = "Key";

                PopulateRepository();
                PopulateOptions();

                if (!conn.CheckMinVersion("0.6.1"))
                {
                    colOnlineURL.Width += colOnlineName.Width;
                    colOnlineName.Width = 0;
                    buttonRefreshOnlineRepository.Visible = false;
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void RefreshRepository()
        {
            try
            {
                if (conn == null)
                    return;

                conn.Repository.Refresh();

                PopulateRepository();
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void PopulateRepository()
        {
            try
            {
                if (conn == null)
                    return;

                listViewFolders.Items.Clear();

                foreach (ServiioSharedFolder folder in conn.Repository.SharedFolders)
                {
                    ListViewItem folderItem = new ListViewItem("");
                    folderItem.ImageKey = folder.ShareVideo ? "VIDEO" : "EMPTY";

                    FancyListView.ImageSubItem musicItem = new FancyListView.ImageSubItem();
                    musicItem.ImageKey = folder.ShareAudio ? "MUSIC" : "EMPTY";
                    folderItem.SubItems.Add(musicItem);

                    FancyListView.ImageSubItem photoItem = new FancyListView.ImageSubItem();
                    photoItem.ImageKey = folder.ShareImages ? "PHOTO" : "EMPTY";
                    folderItem.SubItems.Add(photoItem);

                    folderItem.SubItems.Add(folder.FolderPath);

                    FancyListView.ImageSubItem metaItem = new FancyListView.ImageSubItem();
                    metaItem.ImageKey = folder.DescriptiveMetadataSupported ? "META" : "EMPTY";
                    folderItem.SubItems.Add(metaItem);

                    FancyListView.ImageSubItem scanItem = new FancyListView.ImageSubItem();
                    scanItem.ImageKey = folder.ScanForUpdates ? "SCAN" : "EMPTY";
                    folderItem.SubItems.Add(scanItem);

                    listViewFolders.Items.Add(folderItem);
                }

                listViewOnlineSources.Items.Clear();

                foreach (ServiioOnlineRepository repository in conn.Repository.OnlineRepositories)
                {
                    ListViewItem repositoryItem = new ListViewItem("");
                    repositoryItem.ImageKey = repository.FileType == ServiioOnlineRepository.FileTypes.Video ? "VIDEO" : "EMPTY";

                    FancyListView.ImageSubItem musicItem = new FancyListView.ImageSubItem();
                    musicItem.ImageKey = repository.FileType == ServiioOnlineRepository.FileTypes.Audio ? "MUSIC" : "EMPTY";
                    repositoryItem.SubItems.Add(musicItem);

                    FancyListView.ImageSubItem photoItem = new FancyListView.ImageSubItem();
                    photoItem.ImageKey = repository.FileType == ServiioOnlineRepository.FileTypes.Image ? "PHOTO" : "EMPTY";
                    repositoryItem.SubItems.Add(photoItem);

                    repositoryItem.SubItems.Add(repository.RepositoryName);
                    repositoryItem.SubItems.Add(repository.ContentURL);

                    listViewOnlineSources.Items.Add(repositoryItem);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void PopulateOptions()
        {
            try
            {
                checkBoxAutoUpdate.Checked = conn.Repository.AutomaticLibraryUpdate;
                textBoxAutoUpdateInterval.Text = conn.Repository.AutomaticLibraryUpdateInterval.ToString();
                checkBoxUpdates.Checked = conn.Repository.SearchForUpdates;
                checkBoxHidden.Checked = conn.Repository.SearchHiddenFiles;

                comboBoxMaxNumberOfItemsForOnlineFeeds.SelectedValue = conn.Repository.MaxNumberOfItemsForOnlineFeeds;
                textBoxOnlineFeedExpiryInterval.Text = conn.Repository.OnlineFeedExpiryInterval.ToString();
                comboBoxOnlineContentPreferredQuality.SelectedValue = conn.Repository.OnlineContentPreferredQuality;

                buttonSave.Enabled = false;
                buttonCancel.Enabled = false;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void EditFolder(ListViewItem item)
        {
            try
            {
                ServiioSharedFolder selectedFolder = null;
                String folderPath = item.SubItems[3].Text;
                foreach (ServiioSharedFolder folder in conn.Repository.SharedFolders)
                {
                    if (folder.FolderPath.Equals(folderPath))
                        selectedFolder = folder;
                }

                if (selectedFolder != null)
                {
                    FolderDetailsForm dialog = new FolderDetailsForm();
                    if (dialog.Edit(conn, selectedFolder))
                    {
                        if (!conn.Repository.Update())
                            MessageBox.Show("There was an error updating the Library", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        RefreshRepository();
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void RemoveFolder(ListViewItem item)
        {
            try
            {
                ServiioSharedFolder selectedFolder = null;
                String folderPath = item.SubItems[3].Text;
                foreach (ServiioSharedFolder folder in conn.Repository.SharedFolders)
                {
                    if (folder.FolderPath.Equals(folderPath))
                        selectedFolder = folder;
                }

                if (selectedFolder != null)
                {
                    if (MessageBox.Show("Are you sure you want to remove this shared folder?", "Remove confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                        return;

                    conn.Repository.SharedFolders.Remove(selectedFolder);
                    if (!conn.Repository.Update())
                        MessageBox.Show("There was an error updating the Library", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RefreshRepository();
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void EditRepository(ListViewItem item)
        {
            try
            {
                ServiioOnlineRepository selectedRepository = null;
                String contentURL = item.SubItems[4].Text;
                foreach (ServiioOnlineRepository repository in conn.Repository.OnlineRepositories)
                {
                    if (repository.ContentURL.Equals(contentURL))
                        selectedRepository = repository;
                }

                if (selectedRepository != null)
                {
                    SourceDetailsForm dialog = new SourceDetailsForm();
                    if (dialog.Edit(conn, selectedRepository))
                    {
                        if (!conn.Repository.Update())
                            MessageBox.Show("There was an error updating the Library", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        RefreshRepository();
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void RemoveRepository(ListViewItem item)
        {
            try
            {
                ServiioOnlineRepository selectedRepository = null;
                String contentURL = item.SubItems[4].Text;
                foreach (ServiioOnlineRepository repo in conn.Repository.OnlineRepositories)
                {
                    if (repo.ContentURL.Equals(contentURL))
                        selectedRepository = repo;
                }

                if (selectedRepository != null)
                {
                    if (MessageBox.Show("Are you sure you want to remove this online source?", "Remove confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                        return;

                    conn.Repository.OnlineRepositories.Remove(selectedRepository);
                    if (!conn.Repository.Update())
                        MessageBox.Show("There was an error updating the Library", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RefreshRepository();
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void panelSidebarTitle_Paint(object sender, PaintEventArgs e)
        {
            try
            {
                GuiHelper.GradientTitleBar(e, panelSidebarTitle, "Library Options", Properties.Resources.Multimedia24);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void panelSidebar_Paint(object sender, PaintEventArgs e)
        {
            try
            {
                GuiHelper.PanelBorder(e, panelSidebar);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void panelLeftColumn_Paint(object sender, PaintEventArgs e)
        {
            try
            {
                GuiHelper.PanelBorder(e, panelLeftColumn);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void LibraryTabControl_Load(object sender, EventArgs e)
        {
            try
            {
                imageList32.Images.Add("EMPTY", Properties.Resources.Transparent32);
                imageList32.Images.Add("VIDEO", Properties.Resources.VideoClip32);
                imageList32.Images.Add("MUSIC", Properties.Resources.MusicDouble32);
                imageList32.Images.Add("PHOTO", Properties.Resources.PictureB32);
                imageList32.Images.Add("SCAN", Properties.Resources.AutoScanFolders);
                imageList32.Images.Add("META", Properties.Resources.RetrieveMetadata);

                imageList48.Images.Add(Properties.Resources.LibraryIdle);
                imageList48.Images.Add(Properties.Resources.LibraryScan1);
                imageList48.Images.Add(Properties.Resources.LibraryScan2);
                imageList48.Images.Add(Properties.Resources.LibraryScan3);
                imageList48.Images.Add(Properties.Resources.LibraryScan4);
                imageList48.Images.Add(Properties.Resources.LibraryScan5);
                imageList48.Images.Add(Properties.Resources.LibraryScan6);
                imageList48.Images.Add(Properties.Resources.LibraryScan7);
                imageList48.Images.Add(Properties.Resources.LibraryScan8);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void LibraryScanActive()
        {
            try
            {
                timerAnimate.Enabled = true;
                labelScanStatus.Text = "Updating library...";
                timerLibraryStatus.Interval = 5000;
                buttonForceUpdate.Enabled = false;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void LibraryScanIdle()
        {
            try
            {
                timerAnimate.Enabled = false;
                labelScanStatus.Text = "Idle.";
                pictureBoxScanStatus.Image = imageList48.Images[0];
                timerLibraryStatus.Interval = 10000;
                buttonForceUpdate.Enabled = true;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }
        
        private int currentScanImage = 0;
        private void timerAnimate_Tick(object sender, EventArgs e)
        {
            try
            {
                if (++currentScanImage > 8)
                    currentScanImage = 1;

                pictureBoxScanStatus.Image = imageList48.Images[currentScanImage];
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void timerLibraryStatus_Tick(object sender, EventArgs e)
        {
            try
            {
                if (conn == null)
                    return;

                ServiioLibraryStatus status = conn.GetLibraryStatus();
                if (status == null)
                    return;

                if (status.IsUpdatesCheckerRunning || status.IsAdditionsCheckerRunning)
                    LibraryScanActive();
                else
                    LibraryScanIdle();
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {
            try
            {
                FolderDetailsForm dialog = new FolderDetailsForm();
                ServiioSharedFolder newFolder = dialog.New(conn);
                if (newFolder != null)
                {
                    conn.Repository.SharedFolders.Add(newFolder);
                    if (!conn.Repository.Update())
                        MessageBox.Show("There was an error updating the Library", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RefreshRepository();
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonEdit_Click(object sender, EventArgs e)
        {
            try
            {
                if (listViewFolders.SelectedItems.Count == 0)
                    return;

                EditFolder(listViewFolders.SelectedItems[0]);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonRemove_Click(object sender, EventArgs e)
        {
            try
            {
                if (listViewFolders.SelectedItems.Count == 0)
                    return;

                RemoveFolder(listViewFolders.SelectedItems[0]);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonRefresh_Click(object sender, EventArgs e)
        {
            try
            {
                RefreshRepository();
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void listViewFolders_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            try
            {
                ListViewHitTestInfo hit = listViewFolders.HitTest(e.Location);
                if (hit.Item != null)
                {
                    EditFolder(hit.Item);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void listViewFolders_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
                if (listViewFolders.SelectedItems.Count == 0)
                    return;

                if (e.KeyChar == (char)Keys.Enter)
                    EditFolder(listViewFolders.SelectedItems[0]);
                else if (e.KeyChar == (char)Keys.Delete)
                    RemoveFolder(listViewFolders.SelectedItems[0]);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void checkBoxAutoUpdate_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                textBoxAutoUpdateInterval.Enabled = checkBoxAutoUpdate.Checked;
                labelAutoUpdateIntervalA.Enabled = checkBoxAutoUpdate.Checked;
                labelAutoUpdateIntervalB.Enabled = checkBoxAutoUpdate.Checked;
                buttonSave.Enabled = true;
                buttonCancel.Enabled = true;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void textBoxAutoUpdateInterval_TextChanged(object sender, EventArgs e)
        {
            try
            {
                buttonSave.Enabled = true;
                buttonCancel.Enabled = true;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void checkBoxUpdates_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                buttonSave.Enabled = true;
                buttonCancel.Enabled = true;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void checkBoxHidden_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                buttonSave.Enabled = true;
                buttonCancel.Enabled = true;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            try
            {
                conn.Repository.AutomaticLibraryUpdate = checkBoxAutoUpdate.Checked;
                conn.Repository.AutomaticLibraryUpdateInterval = int.Parse(textBoxAutoUpdateInterval.Text);
                conn.Repository.SearchForUpdates = checkBoxUpdates.Checked;
                conn.Repository.SearchHiddenFiles = checkBoxHidden.Checked;

                conn.Repository.MaxNumberOfItemsForOnlineFeeds = (int)comboBoxMaxNumberOfItemsForOnlineFeeds.SelectedValue;
                try
                {
                    conn.Repository.OnlineFeedExpiryInterval = int.Parse(textBoxOnlineFeedExpiryInterval.Text);
                }
                catch
                {
                    MessageBox.Show("The value for Expire After must be a number.", "Invalid Value", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                conn.Repository.OnlineContentPreferredQuality = (string)comboBoxOnlineContentPreferredQuality.SelectedValue;

                if (!conn.Repository.Update())
                    MessageBox.Show("There was an error updating the Library", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                log.Error(ex);
                conn.Repository.Refresh();
            }
            PopulateOptions();
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            PopulateOptions();
        }

        private void buttonForceUpdate_Click(object sender, EventArgs e)
        {
            try
            {
                conn.ForceLibraryRefresh();
                LibraryScanActive();
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonPresentationOptions_Click(object sender, EventArgs e)
        {
            try
            {
                PresentationOptionsForm dialog = new PresentationOptionsForm();
                dialog.Edit(conn);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void comboBoxMaxNumberOfItemsForOnlineFeeds_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                buttonSave.Enabled = true;
                buttonCancel.Enabled = true;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }

        }

        private void textBoxOnlineFeedExpiryInterval_TextChanged(object sender, EventArgs e)
        {
            try
            {
                buttonSave.Enabled = true;
                buttonCancel.Enabled = true;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void comboBoxOnlineContentPreferredQuality_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                buttonSave.Enabled = true;
                buttonCancel.Enabled = true;
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonOnlineAdd_Click(object sender, EventArgs e)
        {
            try
            {
                SourceDetailsForm dialog = new SourceDetailsForm();
                ServiioOnlineRepository newSource = dialog.New(conn);
                if (newSource != null)
                {
                    conn.Repository.OnlineRepositories.Add(newSource);
                    if (!conn.Repository.Update())
                        MessageBox.Show("There was an error updating the Library", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    RefreshRepository();
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonOnlineEdit_Click(object sender, EventArgs e)
        {
            try
            {
                if (listViewOnlineSources.SelectedItems.Count == 0)
                    return;

                EditRepository(listViewOnlineSources.SelectedItems[0]);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonOnlineRemove_Click(object sender, EventArgs e)
        {
            try
            {
                if (listViewOnlineSources.SelectedItems.Count == 0)
                    return;

                RemoveRepository(listViewOnlineSources.SelectedItems[0]);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void listViewOnlineSources_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            try
            {
                ListViewHitTestInfo hit = listViewOnlineSources.HitTest(e.Location);
                if (hit.Item != null)
                {
                    EditRepository(hit.Item);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void listViewOnlineSources_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
                if (listViewOnlineSources.SelectedItems.Count == 0)
                    return;

                if (e.KeyChar == (char)Keys.Enter)
                    EditRepository(listViewOnlineSources.SelectedItems[0]);
                else if (e.KeyChar == (char)Keys.Delete)
                    RemoveRepository(listViewOnlineSources.SelectedItems[0]);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void buttonRefreshOnlineRepository_Click(object sender, EventArgs e)
        {
            try
            {
                if (listViewOnlineSources.SelectedItems.Count == 0)
                    return;

                ServiioOnlineRepository selectedRepository = null;
                String contentURL = listViewOnlineSources.SelectedItems[0].SubItems[4].Text;
                foreach (ServiioOnlineRepository repository in conn.Repository.OnlineRepositories)
                {
                    if (repository.ContentURL.Equals(contentURL))
                        selectedRepository = repository;
                }

                if (selectedRepository != null)
                {
                    conn.ForceOnlineRepositoryRefresh(selectedRepository.Id);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }
    }
}
